﻿using System;

namespace Present.Commands.Async.Actions
{
    public interface IAsyncAction<TParameter, TResult> : IAsyncAction
    {
        void HandleSuccess(TResult result);
        TResult DoWork(ActionExecution<TParameter> execution);
        ActionExecution<TParameter> PrepareWork(TParameter parameter);
    }

    public interface IAsyncAction
    {
        void HandleSuccess(object result);
        void HandleError(Exception error);
        void HandleCancel(ActionExecution execution);
        object DoWork(ActionExecution parameter);
        ActionExecution PrepareWork(object parameter);
        bool CanExecute(object parameter);
        event EventHandler<EventArgs> CanExecuteChanged;
    }

    public class ActionExecution
    {
        public ActionExecution(object parameter)
        {
            Parameter = parameter;
        }

        public object Parameter { get; private set; }
        public bool CancelRequested { get; set; }

        static ActionExecution()
        {
            Empty = new ActionExecution<object>(new object());
        }

        public static ActionExecution<object> Empty { get; private set; }
    }

    public class ActionExecution<TParameter> : ActionExecution
    {
        public ActionExecution(TParameter parameter)
            : base(parameter)
        {
        }

        public new TParameter Parameter { get { return (TParameter)base.Parameter; } }
    }
}